package com.yami.shop.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yami.shop.bean.model.MeltCloudGroupUserInvite;
import com.yami.shop.bean.model.MeltCloudUser;
import com.yami.shop.bean.model.MeltCloudUserRemark;
import com.yami.shop.common.bean.PageDTO;
import com.yami.shop.common.bean.PageVO;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageUtil;
import com.yami.shop.common.util.StringUtils;
import com.yami.shop.dto.user.RegisterRongReqDTO;
import com.yami.shop.service.MeltCloudGroupUserInviteService;
import com.yami.shop.service.MeltCloudUserRemarkService;
import com.yami.shop.service.MeltCloudUserService;
import com.yami.shop.util.SendUtil;
import io.rong.RongCloud;
import io.rong.methods.user.User;
import io.rong.models.Result;
import io.rong.models.response.*;
import io.rong.models.user.ExpireModel;
import io.rong.models.user.UserModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * UserServiceImpl
 *
 * @author RongCloud
 */
@Slf4j
@Service
public class RongYunUserServiceImpl {
    @Autowired
    private RongCloud rongCloud;

    private User User;
    @Autowired
    private MeltCloudGroupUserInviteService meltCloudGroupUserInviteService;
    @Autowired
    private MeltCloudUserRemarkService userRemarkService;

    @PostConstruct
    public void init() {
        this.User = rongCloud.user;
    }

    @Autowired
    private MeltCloudUserService userService;
    @Transactional(rollbackFor = Exception.class)
    public void userGetTokenBatch() throws Exception {
        List<MeltCloudUser> list = userService.list();
        list.forEach(meltCloudUser->{
            UserModel user = new UserModel()
                    .setId(meltCloudUser.getId())
                    .setName(meltCloudUser.getUserName())
                    .setPortrait(meltCloudUser.getUserPortrait());
            try {
                TokenResult result = null;
                result = User.register(user);
                // 2. 修改融云用户记录token
                if (ObjectUtil.isNotNull(result)) {
                    if (result.getCode() == 200) {
                        // 1. 保存融云用户token
                        meltCloudUser.setUserToken(result.getToken());
                        meltCloudUser.setCreateDate(LocalDateTime.now());
                        userService.updateById(meltCloudUser);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 创建融云用户
     * 系统id为融云用户id
     *
     * @param registerRongReqVO
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public ServerResponseEntity<String> userRegister(RegisterRongReqDTO registerRongReqVO) throws Exception {
        MeltCloudUser one = userService.getById(registerRongReqVO.getId());
        if (Objects.isNull(one)) {
            UserModel user = new UserModel()
                    .setId(registerRongReqVO.getId())
                    .setName(registerRongReqVO.getName())
                    .setPortrait(registerRongReqVO.getPortrait());
            // 1. 保存融云用户
            MeltCloudUser cloudUser = MeltCloudUser.builder()
                    .id(registerRongReqVO.getId())
                    .userName(user.getName())
                    .createDate(LocalDateTime.now())
                    .userPortrait(user.getPortrait())
                    .build();
            TokenResult result = User.register(user);
            // 2. 修改融云用户记录token
            if (ObjectUtil.isNotNull(result)) {
                if (result.getCode() == 200) {
                    cloudUser.setUserToken(result.getToken());
                    userService.registeredRongYunUser(cloudUser);
                    return ServerResponseEntity.success(result.getToken());
                }
            }
            throw new YamiShopBindException("注册融云用户失败");
        } else {
            return ServerResponseEntity.success();
        }
    }

    /**
     * API 文档: http://www.rongcloud.cn/docs/server_sdk_api/user/user.html#refresh
     * <p>
     * 更新用户信息方法
     */
    public ServerResponseEntity<String> userRefresh(RegisterRongReqDTO registerRongReqVO) throws Exception {
        UserModel user = new UserModel().setId(String.valueOf(registerRongReqVO.getId())).setName(registerRongReqVO.getName());
        Result refreshResult = User.update(user);
        log.info("refresh:  " + refreshResult.toString());
        if (SendUtil.requestSuccess(refreshResult)) {
            MeltCloudUser cloudUser = MeltCloudUser.builder()
                    .userPortrait(registerRongReqVO.getPortrait())
                    .userName(registerRongReqVO.getName())
                    .id(registerRongReqVO.getId())
                    .build();
            userService.updateById(cloudUser);
            return ServerResponseEntity.success();
        }
        throw new YamiShopBindException("刷新用户信息异常");
    }

    /**
     * API 文档: http://www.rongcloud.cn/docs/server_sdk_api/user/user.html#get
     * <p>
     * 查询用户信息方法
     */
    public ServerResponseEntity<MeltCloudUser> getUserInfo(String userId, String current) throws Exception {
        UserModel user = new UserModel().setId(userId);
        UserResult userResult = User.get(user);
        log.info("userId: " + userId + "，getUserInfo:  " + userResult.toString());
        if (SendUtil.requestSuccess(userResult)) {
            MeltCloudUser cloudUser = userService.getById(userId);
            if (cloudUser != null) {
                if (StringUtils.isNotEmpty(current)) {
                    MeltCloudUserRemark one = userRemarkService.getOne(Wrappers.lambdaQuery(MeltCloudUserRemark.class)
                            .eq(MeltCloudUserRemark::getUserId, current).eq(MeltCloudUserRemark::getType, 1).eq(MeltCloudUserRemark::getObjId, userId));
                    if (one != null && StringUtils.isNotEmpty(one.getRemark()))
                        cloudUser.setUserName(one.getRemark());
                }
                CheckOnlineResult result = User.onlineStatus.check(user);
                if (SendUtil.requestSuccess(result)) {
                    cloudUser.setOnlineStatus(StrUtil.equals(result.getStatus(), "1"));
                }
                return ServerResponseEntity.success(cloudUser);
            }
        }
        throw new YamiShopBindException("获取用户信息异常");
    }

    /**
     * 获取用户列表
     *
     * @param pageDTO
     * @param userName
     * @return
     */
    public PageVO<MeltCloudUser> userAll(PageDTO pageDTO, String userName) throws Exception {
        PageVO<MeltCloudUser> vo = PageUtil.doPage(pageDTO, () -> userService.list(new LambdaQueryWrapper<MeltCloudUser>().like(StrUtil.isNotEmpty(userName), MeltCloudUser::getUserName, userName)));
        for (MeltCloudUser meltCloudUser : vo.getList()) {
            UserModel user = new UserModel().setId(meltCloudUser.getId());
            CheckOnlineResult result = User.onlineStatus.check(user);
            if (SendUtil.requestSuccess(result)) {
                meltCloudUser.setOnlineStatus(StrUtil.equals(result.getStatus(), "1"));
            }
        }
        return vo;
    }


    /**
     * API 文档: http://www.rongcloud.cn/docs/server_sdk_api/user/user.html#get
     * <p>
     * 查询用户所在群组
     */
    public ServerResponseEntity<UserGroupQueryResult> getGroups(String userId) {
        UserModel user = new UserModel().setId(userId);
        UserGroupQueryResult userGroupResult;
        try {
            userGroupResult = User.getGroups(user);
        } catch (Exception e) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        log.info("getGroups:  " + userGroupResult.toString());
        if (ObjectUtil.isNotNull(userGroupResult)) {
            if (userGroupResult.getCode() == 200) {
                return ServerResponseEntity.success(userGroupResult);
            }
        }
        return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);
    }

    /**
     * API 文档: https://docs.rongcloud.cn/v4/5X/views/im/server/user/expire.html
     * <p>
     * Token 失效
     */
    public ServerResponseEntity<String> userExpire(List<String> userIds) {
        String[] userIdStr = userIds.toArray(new String[0]);
        ExpireModel expireModel = new ExpireModel().setUserId(userIdStr).setTime(new Date().getTime());
        Result refreshResult;
        try {
            refreshResult = User.expire(expireModel);
        } catch (Exception e) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        log.info("expire:  " + refreshResult.toString());
        if (ObjectUtil.isNotNull(refreshResult)) {
            if (refreshResult.getCode() == 200) {
                return ServerResponseEntity.success();
            } else {
                return ServerResponseEntity.fail(refreshResult.getCode(), refreshResult.getErrorMessage());
            }
        }
        return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);
    }

    /**
     * 用户注销
     */
    public ServerResponseEntity<String> abandon(String userId) throws Exception {
        UserModel user = new UserModel().setId(userId);
        ResponseResult abandon = User.abandon(user);
        log.info("user abandon:  " + abandon.toString());
        LambdaUpdateWrapper<MeltCloudUser> meltCloudUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        meltCloudUserLambdaUpdateWrapper.eq(MeltCloudUser::getId,userId).set(MeltCloudUser::getDelFlag,1);
        userService.update(meltCloudUserLambdaUpdateWrapper);
        //删除管理申请表
        LambdaQueryWrapper<MeltCloudGroupUserInvite> eq = new LambdaQueryWrapper<MeltCloudGroupUserInvite>();
        eq.eq(MeltCloudGroupUserInvite::getStatus,0);
        eq.and(qw->qw.eq(MeltCloudGroupUserInvite::getUserId,userId).or().eq(MeltCloudGroupUserInvite::getInviteUserId,userId));
        meltCloudGroupUserInviteService.remove(eq);
        return ServerResponseEntity.success();
    }

    /**
     * 注销用户列表
     *
     * @param page
     * @return
     */
    public ServerResponseEntity<List<String>> abandonList(int page, int pageSize) {
        UserAbandonResult abandonList;
        try {
            abandonList = User.abandonList(page, pageSize);
        } catch (Exception e) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        log.info("user abandon list:  " + abandonList.toString());
        if (ObjectUtil.isNotNull(abandonList)) {
            if (abandonList.getCode() == 200) {
                return ServerResponseEntity.success(abandonList.getUsers());
            }
        }
        return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);
    }

    /**
     * 用户激活
     *
     * @param userId
     * @return
     */
    public ServerResponseEntity<String> activate(String userId) {
        UserModel user = new UserModel().setId(userId);
        ResponseResult active;
        try {
            active = User.activate(user);
        } catch (Exception e) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        log.info("user activate set:  " + active.toString());
        if (ObjectUtil.isNotNull(active)) {
            if (active.getCode() == 200) {
                return ServerResponseEntity.success(active.getReqBody());
            } else {
                return ServerResponseEntity.fail(active.getCode(), active.getErrorMessage());
            }
        }
        return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);
    }

    public ServerResponseEntity<String> checkOnline(String userId) {
        UserModel user = new UserModel().setId(userId);

        CheckOnlineResult result;
        try {
            result = User.onlineStatus.check(user);
        } catch (Exception e) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        log.info("checkOnline:  " + result.toString());
        if (ObjectUtil.isNotNull(result)) {
            if (result.getCode() == 200) {
                return ServerResponseEntity.success();
            } else {
                return ServerResponseEntity.fail(result.getCode(), result.getErrorMessage());
            }
        }
        return ServerResponseEntity.fail(ResponseEnum.CLEAN_TOKEN);

    }

}
